<!DOCTYPE html>
<html lang="zh-CN">





<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/blog/img/favicon.png">
  <link rel="icon" type="image/png" href="/blog/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
  
  <meta name="theme-color" content="#35495e">
  <meta name="description" content="小菜头的博客，主要记录学习笔记，包含：html,css,javascript,jQuery,vue等">
  <meta name="author" content="A-cai">
  <meta name="keywords" content="html,css,javascript,jQuery,vue">
  <title>vue - A-cai的blog</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/blog/lib/hint/hint.min.css" />

  
    <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/atom-one-dark.min.css" />
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_yg9cfy8wd6.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_pjno9b9zyxs.css">


<link  rel="stylesheet" href="/blog/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/blog/js/utils.js" ></script>
<meta name="generator" content="Hexo 4.2.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/blog/">&nbsp;<strong>A-cai的学习笔记</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('/blog/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container text-center white-text fade-in-up">
            <span class="h2" id="subtitle">
              
            </span>

            
              
  <div class="mt-3 post-meta">
    <i class="iconfont icon-date-fill" aria-hidden="true"></i>
    <time datetime="2020-06-26 14:04">
      2020年6月26日 下午
    </time>
  </div>


<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      2.9k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      33
       分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <div class="post-content mx-auto" id="post">
            
              <p class="note note-info">
                
                  本文最后更新于：2020年3月9日 晚上
                
              </p>
            
            <article class="markdown-body">
              <h1 id="Vue"><a href="#Vue" class="headerlink" title="Vue"></a>Vue</h1><p>什么是mvvm</p>
<p>MVVM最早由微软提出来，它借鉴了桌面应用程序的MVC思想，在前端页面中，把Model用纯JavaScript对象表示，View负责显示，两者做到了最大限度的分离<br>把Model和View关联起来的就是ViewModel。<br><br>ViewModel负责把Model的数据同步到View显示出来，还负责把View的修改同步回Model<br><br>View 和 Model 之间的同步工作完全是自动的，无需人为干涉（由viewModel完成，在这里指VUE）<br><br>因此开发者只需关注业务逻辑，不需要手动操作DOM, 不需要关注数据状态的同步问题，复杂的数据状态维护完全由 MVVM 来统一管理<br></p>
<h4 id="ViewModel如何编写？"><a href="#ViewModel如何编写？" class="headerlink" title="ViewModel如何编写？"></a>ViewModel如何编写？</h4><p>需要用JavaScript编写一个通用的ViewModel，这样，就可以复用整个MVVM模型了</p>
<p>一个MVVM框架和jQuery操作DOM相比有什么区别？<br>我们先看用jQuery实现的修改两个DOM节点的例子：</p>
<div class="hljs"><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- HTML --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello, <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span>&gt;</span>Bart<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>You are <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"age"</span>&gt;</span>12<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

Hello, Bart!

You are 12.</code></pre></div>
<p>用jQuery修改name和age节点的内容：</p>
<div class="hljs"><pre><code class="hljs arcade"><span class="hljs-keyword">var</span> name = <span class="hljs-string">'Homer'</span>;
<span class="hljs-keyword">var</span> age = <span class="hljs-number">51</span>;

$(<span class="hljs-string">'#name'</span>).text(name);
$(<span class="hljs-string">'#age'</span>).text(age);</code></pre></div>

<p>如果我们使用MVVM框架来实现同样的功能，我们首先并不关心DOM的结构，而是关心数据如何存储。最简单的数据存储方式是使用JavaScript对象：</p>
<div class="hljs"><pre><code class="hljs properties"><span class="hljs-attr">var</span> <span class="hljs-string">person = &#123;</span>
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Bart',</span>
    <span class="hljs-attr">age</span>: <span class="hljs-string">12</span>
<span class="hljs-attr">&#125;</span></code></pre></div>
<p>我们把变量person看作Model，把HTML某些DOM节点看作View，并假定它们之间被关联起来了。</p>
<p>要把显示的name从Bart改为Homer，把显示的age从12改为51，我们并不操作DOM，而是直接修改JavaScript对象：</p>
<div class="hljs"><pre><code class="hljs ini"><span class="hljs-attr">person.name</span> = <span class="hljs-string">'Homer'</span><span class="hljs-comment">;</span>
<span class="hljs-attr">person.age</span> = <span class="hljs-number">51</span><span class="hljs-comment">;</span></code></pre></div>

<p>执行上面的代码，我们惊讶地发现，改变JavaScript对象的状态，会导致DOM结构作出对应的变化！这让我们的关注点从如何操作DOM变成了如何更新JavaScript对象的状态，而操作JavaScript对象比DOM简单多了！</p>
<p>这就是MVVM的设计思想：关注Model的变化，让MVVM框架去自动更新DOM的状态，从而把开发者从操作DOM的繁琐步骤中解脱出来！<br>下图可以很好的解释view viewModel model之间的关系<br><img src="https://github.com/woai3c/mini-vue/blob/master/imgs/mvvm.jpg" srcset="/blog/img/loading.gif" alt="mvvm"></p>
<h4 id="回到顶部"><a href="#回到顶部" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="Vue的优点是什么"><a href="#Vue的优点是什么" class="headerlink" title="Vue的优点是什么"></a>Vue的优点是什么</h2><p>mvvm的优点即是vue的优点，在这里再总结一下：<br><br>数据和视频之间的同步工作完全是自动的，无需人为干涉，所以开发者只需关注业务逻辑，不需要手动操作DOM, 不需要关注数据状态的同步问题，<br>复杂的数据状态维护完全由 MVVM 来统一管理，节省了很多精力。</p>
<h4 id="回到顶部-1"><a href="#回到顶部-1" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="对于生命周期的理解"><a href="#对于生命周期的理解" class="headerlink" title="对于生命周期的理解"></a>对于生命周期的理解</h2><p>创建一个Vue实例，是一个漫长的过程，要经历初始化，数据合并，模板解析，数据渲染等等一系列过程。<br>所以，为了能实现在这个过程里面插入自己想要提前做的事情，就有了生命周期钩子函数。</p>
<h4 id="举个例子："><a href="#举个例子：" class="headerlink" title="举个例子："></a>举个例子：</h4><div class="hljs"><pre><code class="hljs armasm">一辆公交车，从出发点A站到终点站<span class="hljs-keyword">B，中间有很多站点，公交车每到一个站点，就得停下来，</span>
<span class="hljs-keyword">等待客人上车，然后再驶往下一个站点，一直到终点站为止。</span>
<span class="hljs-keyword">A和B之间的站点，就像是这个路程的生命周期。每一个站点都是一个不同的生命周期（站点名不同），</span>
<span class="hljs-keyword">只要到了站点，就得执行该站点对应的生命周期函数，</span>
<span class="hljs-keyword">只不过每个站点的生命周期函数都是一样的（等待客人上车）。</span></code></pre></div>
<p>Vue中的生命周期也是一样，对应了Vue实例从创建到结束之间的每一个过程。<br>例如，Vue的<code>beforeCreate</code>周期，指的就是Vue在实例初始化之后，数据观测 (data observer) 和 event/watcher 事件配置之前被调用。</p>
<p>至于Vue具体的生命周期函数有哪些，请看官网<a href="https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90" target="_blank" rel="noopener">API文档</a></p>
<h4 id="回到顶部-2"><a href="#回到顶部-2" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="组件传值"><a href="#组件传值" class="headerlink" title="组件传值"></a>组件传值</h2><ul>
<li>父组件通过prop向子组件传值</li>
<li>子组件通过事件向父组件传值</li>
<li>子组件与子组件之间不能直接传值，需要通过父组件来做间接传值，在这种情况下推荐使用vuex</li>
</ul>
<p>具体例子请看<a href="https://cn.vuejs.org/v2/guide/components.html#%E9%80%9A%E8%BF%87-Prop-%E5%90%91%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BC%A0%E9%80%92%E6%95%B0%E6%8D%AE" target="_blank" rel="noopener">官方文档</a></p>
<h4 id="回到顶部-3"><a href="#回到顶部-3" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="vue数据绑定原理"><a href="#vue数据绑定原理" class="headerlink" title="vue数据绑定原理"></a>vue数据绑定原理</h2><p>Vue的数据双向绑定都是依据Object.defineProperty()这一方法来做的<br><br>Object.defineProperty到底有什么作用呢？<br><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty" target="_blank" rel="noopener">MDN</a></p>
<div class="hljs"><pre><code class="hljs reasonml"><span class="hljs-module-access"><span class="hljs-module"><span class="hljs-identifier">Object</span>.</span></span>define<span class="hljs-constructor">Property(<span class="hljs-params">obj</span>, <span class="hljs-params">prop</span>, <span class="hljs-params">descriptor</span>)</span>

obj
要在其上定义属性的对象。

prop
要定义或修改的属性的名称。

descriptor
将被定义或修改的属性描述符。</code></pre></div>
<p>简单来说 这个方法可以定义一个对象某个属性的描述符</p>
<p>我们需要用到的就是描述符当中的getter和setter</p>
<div class="hljs"><pre><code class="hljs angelscript"><span class="hljs-keyword">const</span> obj = &#123;a:<span class="hljs-number">1</span>&#125;
obj.a <span class="hljs-comment">// 1</span>

obj.a = <span class="hljs-number">2</span></code></pre></div>
<p>像上面代码中的两个操作 读取和赋值 就是在访问obj.a的getter和setter<br><br>当我们输入obj.a时 就是在访问obj对象a属性的getter 当输入obj.a = 2 时就是在访问obj对象a属性的setter</p>
<div class="hljs"><pre><code class="hljs actionscript">Object.defineProperty(obj, <span class="hljs-string">'a'</span>, &#123;
  <span class="hljs-keyword">get</span> : <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>&#123;
    <span class="hljs-keyword">return</span> val
  &#125;,
  <span class="hljs-keyword">set</span> : <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(newValue)</span></span>&#123;
    val = newValue
  &#125;,
  enumerable : <span class="hljs-literal">true</span>,
  configurable : <span class="hljs-literal">true</span>
&#125;)</code></pre></div>
<p>getter和setter都是一个函数 我们还可以这样做 例如</p>
<div class="hljs"><pre><code class="hljs actionscript"><span class="hljs-keyword">get</span>: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>&#123;
  <span class="hljs-comment">// 每次访问obj.a时都会执行这段代码</span>
  console.log(<span class="hljs-string">'hello, 你在读取a的值'</span>)
  <span class="hljs-keyword">return</span> val
&#125;
<span class="hljs-keyword">set</span>: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(newValue)</span> </span>&#123;
  val = newValue
  <span class="hljs-comment">// 每次给obj.a赋值时都会执行这段代码</span>
  console.log(<span class="hljs-string">'你设置了a的值'</span>)
&#125;</code></pre></div>
<p>Vue的双向数据绑定就是根据上面的原理来实现的<br>只要在读取值时收集观察者 在赋值时触发观察者更新函数 就可以实现数据变更 从而实现DOM重新渲染</p>
<p>说到这可能还不是很明白 不要急 慢慢来 先看一下这段代码 复制放到HTML文件里自己运行一下<br>然后打开网页 在控制台里输入data.user.name看看 会有惊喜 </p>
<div class="hljs"><pre><code class="hljs xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>动态数据绑定（一）<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span>
<span class="actionscript">    <span class="hljs-keyword">var</span> data = &#123;</span>
        user: &#123;
<span class="actionscript">            name: <span class="hljs-string">'xiaoming'</span>,</span>
            age: 18,
<span class="actionscript">            occupation: <span class="hljs-string">'frontend'</span></span>
        &#125;,
        address: &#123;
<span class="actionscript">            city: <span class="hljs-string">'shaoguan'</span></span>
        &#125;
    &#125;; 
<span class="actionscript">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Observer</span><span class="hljs-params">(data)</span> </span>&#123;</span>
<span class="actionscript">        <span class="hljs-keyword">this</span>.data = data;</span>
<span class="actionscript">        <span class="hljs-keyword">this</span>.walk(data);</span>
    &#125;
    Observer.prototype = &#123;
<span class="actionscript">        walk: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(obj)</span> </span>&#123;</span>
<span class="actionscript">            <span class="hljs-keyword">var</span> value,</span>
                key;
            for (key in obj) &#123;
                if (obj.hasOwnProperty(key)) &#123;
                    value = obj[key];
<span class="actionscript">                    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> value === <span class="hljs-string">'object'</span>) &#123;</span>
<span class="actionscript">                        <span class="hljs-keyword">new</span> Observer(value);</span>
                    &#125;
<span class="actionscript">                    <span class="hljs-keyword">this</span>.convert(key, value); </span>
                &#125;   
            &#125;
        &#125;,
<span class="actionscript">        convert: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(key, value)</span> </span>&#123;</span>
<span class="javascript">            <span class="hljs-built_in">Object</span>.defineProperty(<span class="hljs-keyword">this</span>.data, key, &#123;</span>
<span class="actionscript">                <span class="hljs-keyword">get</span> : <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>&#123; </span>
<span class="javascript">                    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"你访问了"</span> + key);</span>
<span class="actionscript">                    <span class="hljs-keyword">return</span> value; </span>
                &#125;,
<span class="actionscript">                <span class="hljs-keyword">set</span> : <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(newValue)</span></span>&#123; </span>
                    value = newValue; 
<span class="javascript">                    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'你设置了'</span> + key + <span class="hljs-string">'='</span> + value);</span>
                &#125;
            &#125;);
        &#125;
    &#125;  
<span class="actionscript">    <span class="hljs-keyword">var</span> example = <span class="hljs-keyword">new</span> Observer(data);</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>   
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></code></pre></div>

<h4 id="回到顶部-4"><a href="#回到顶部-4" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="vue-router原理"><a href="#vue-router原理" class="headerlink" title="vue-router原理"></a>vue-router原理</h2><p>说简单点，vue-router的原理就是通过对URL地址变化的监听，继而对不同的组件进行渲染。<br><br>每当URL地址改变时，就对相应的组件进行渲染。原理是很简单，实现方式可能有点复杂，主要有hash模式和history模式。<br></p>
<p>#hash不会触发浏览器页面请求，不需要用服务器配合</p>
<p>history是使用history.pushstate(),修改url不会触发浏览器页面请求，需要服务器配合</p>
<p>如果想了解得详细点，建议百度或者阅读源码。</p>
<h4 id="回到顶部-5"><a href="#回到顶部-5" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="vuex原理"><a href="#vuex原理" class="headerlink" title="vuex原理"></a>vuex原理</h2><p>vuex的原理其实非常简单，它为什么能实现所有的组件共享同一份数据？<br><br>因为vuex生成了一个store实例，并且把这个实例挂在了所有的组件上，所有的组件引用的都是同一个store实例。<br><br>store实例上有数据，有方法，方法改变的都是store实例上的数据。由于其他组件引用的是同样的实例，所以一个组件改变了store上的数据，<br>导致另一个组件上的数据也会改变，就像是一个对象的引用。<br><br>如果对vuex的实现有兴趣，可以看看我自己造的一个vue轮子对应的<a href="https://github.com/woai3c/mini-vuex/blob/master/mini-vuex.js" target="_blank" rel="noopener">vuex插件</a>。它实现了除vuex模块外的所有功能。</p>
<h4 id="回到顶部-6"><a href="#回到顶部-6" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="v-if和v-show的区别"><a href="#v-if和v-show的区别" class="headerlink" title="v-if和v-show的区别"></a>v-if和v-show的区别</h2><p><code>v-if</code> 是“真正”的条件渲染，因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。</p>
<p><code>v-if</code> 也是惰性的：如果在初始渲染时条件为假，则什么也不做——直到条件第一次变为真时，才会开始渲染条件块。</p>
<p>相比之下，<code>v-show</code> 就简单得多——不管初始条件是什么，元素总是会被渲染，并且只是简单地基于 CSS 进行切换。</p>
<p>一般来说，<code>v-if</code> 有更高的切换开销，而 <code>v-show</code> 有更高的初始渲染开销。因此，如果需要非常频繁地切换，则使用 <code>v-show</code> 较好；如果在运行时条件很少改变，则使用<code>v-if</code> 较好。</p>
<p><a href="https://cn.vuejs.org/v2/guide/conditional.html#v-if-vs-v-show" target="_blank" rel="noopener">https://cn.vuejs.org/v2/guide/conditional.html#v-if-vs-v-show</a></p>
<h4 id="回到顶部-7"><a href="#回到顶部-7" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="vue怎么实现页面的权限控制"><a href="#vue怎么实现页面的权限控制" class="headerlink" title="vue怎么实现页面的权限控制"></a>vue怎么实现页面的权限控制</h2><p>利用 <code>vue-router</code> 的 <code>beforeEach</code> 事件，可以在跳转页面前判断用户的权限（利用 cookie 或 token，sessionid），是否能够进入此页面，如果不能则提示错误或重定向到其他页面，在后台管理系统中这种场景经常能遇到。</p>
<h4 id="回到顶部-8"><a href="#回到顶部-8" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="keep-alive有什么作用"><a href="#keep-alive有什么作用" class="headerlink" title="keep-alive有什么作用"></a>keep-alive有什么作用</h2><p>在 <code>Vue</code> 中，每次切换组件时，都会重新渲染。如果有多个组件切换，又想让它们保持原来的状态，避免重新渲染，这个时候就可以使用 <code>keep-alive</code>。<br><code>keep-alive</code> 可以使被包含的组件保留状态，或避免重新渲染。</p>
<h4 id="回到顶部-9"><a href="#回到顶部-9" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="计算属性有什么作用"><a href="#计算属性有什么作用" class="headerlink" title="计算属性有什么作用"></a>计算属性有什么作用</h2><p>先来看一下计算属性的定义：<br><br>当其依赖的属性的值发生变化的时，计算属性会重新计算。反之则使用缓存中的属性值。<br><br>计算属性和vue中的其它数据一样，都是响应式的，只不过它必须依赖某一个数据实现，并且只有它依赖的数据的值改变了，它才会更新。</p>
<h4 id="回到顶部-10"><a href="#回到顶部-10" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="route和-router的区别"><a href="#route和-router的区别" class="headerlink" title="$route和$router的区别"></a>$route和$router的区别</h2><p><code>$route</code> 是路由信息对象，包括<code>path</code>，<code>params</code>，<code>hash</code>，<code>query</code>，<code>fullPath</code>，<code>matched</code>，<code>name</code> 等路由信息参数。</p>
<p>而 <code>$router</code> 是路由实例对象，包括了路由的跳转方法，钩子函数等</p>
<h4 id="回到顶部-11"><a href="#回到顶部-11" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="watch的作用是什么"><a href="#watch的作用是什么" class="headerlink" title="watch的作用是什么"></a>watch的作用是什么</h2><p><code>watch</code> 主要作用是监听某个数据值的变化。和计算属性相比除了没有缓存，作用是一样的。</p>
<p>借助 <code>watch</code> 还可以做一些特别的事情，例如监听页面路由，当页面跳转时，我们可以做相应的权限控制，拒绝没有权限的用户访问页面。</p>
<h4 id="回到顶部-12"><a href="#回到顶部-12" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="vue-loader是什么？使用它的用途有哪些？"><a href="#vue-loader是什么？使用它的用途有哪些？" class="headerlink" title="vue-loader是什么？使用它的用途有哪些？"></a>vue-loader是什么？使用它的用途有哪些？</h2><p>vue-loader 是解析 .vue 文件的一个加载器，将 template/js/style 转换成 js 模块。</p>
<p>用途：js 可以写 es6、style 样式可以 scss 或 less；template 可以加 jade 等。</p>
<h4 id="回到顶部-13"><a href="#回到顶部-13" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4><h2 id="假设定义了一个数组a-1-2-3-，相应的，页面上显示的值为1-2-3，现设a-0-5，页面上的值会变成5-2-3吗？为什么？"><a href="#假设定义了一个数组a-1-2-3-，相应的，页面上显示的值为1-2-3，现设a-0-5，页面上的值会变成5-2-3吗？为什么？" class="headerlink" title="假设定义了一个数组a=[1,2,3]，相应的，页面上显示的值为1,2,3，现设a[0]=5，页面上的值会变成5,2,3吗？为什么？"></a>假设定义了一个数组a=[1,2,3]，相应的，页面上显示的值为1,2,3，现设a[0]=5，页面上的值会变成5,2,3吗？为什么？</h2><p>不会</p>
<p>因为 Vue 是使用 <code>Object.defineProperty</code> 来监听数值变化的，而直接修改数组的值的这种操作无法监听。</p>
<p>例如：<code>vm.items[indexOfItem] = newValue</code> 这种操作是无法监听的。</p>
<p>如果需要直接修改数组元素的值，可以使用 <code>Vue.set</code></p>
<div class="hljs"><pre><code class="hljs js">Vue.set(vm.items, indexOfItem, newValue)</code></pre></div>

<p><a href="https://cn.vuejs.org/v2/guide/list.html#%E6%95%B0%E7%BB%84%E6%9B%B4%E6%96%B0%E6%A3%80%E6%B5%8B" target="_blank" rel="noopener">数组更新检测</a></p>
<h4 id="回到顶部-14"><a href="#回到顶部-14" class="headerlink" title="回到顶部"></a><a href="#vue">回到顶部</a></h4>
            </article>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" target="_blank" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <div class="post-prev col-6">
                    
                    
                      <a href="/blog/2020/06/26/%E5%85%B6%E4%BB%96/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">其他</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </div>
                  <div class="post-next col-6">
                    
                    
                      <a href="/blog/2020/06/26/JavaSciprt/">
                        <span class="hidden-mobile">JavaSciprt</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </div>
                </div>
              
            </div>

            
              <!-- Comments -->
              <div class="comments" id="comments">
                
                

              </div>
            
          </div>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  

  <footer class="mt-5">
  <div class="text-center py-3">
    <div>
      <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a>
      <i class="iconfont icon-love"></i>
      <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener">
        <span>Fluid</span></a>
    </div>
    

    

    
  </div>
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/blog/js/debouncer.js" ></script>
<script  src="/blog/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/blog/js/lazyload.js" ></script>
  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/blog/js/clipboard-use.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: 'article.markdown-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "vue&nbsp;",
      ],
      cursorChar: "|",
      typeSpeed: 70,
      loop: true,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>



  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/blog/js/local-search.js" ></script>
  <script>
    var path = "/blog/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>







  
  
    <script>
      !function (e, t, a) {
        function r() {
          for (var e = 0; e < s.length; e++) s[e].alpha <= 0 ? (t.body.removeChild(s[e].el), s.splice(e, 1)) : (s[e].y--, s[e].scale += .004, s[e].alpha -= .013, s[e].el.style.cssText = "left:" + s[e].x + "px;top:" + s[e].y + "px;opacity:" + s[e].alpha + ";transform:scale(" + s[e].scale + "," + s[e].scale + ") rotate(45deg);background:" + s[e].color + ";z-index:99999");
          requestAnimationFrame(r)
        }

        function n() {
          var t = "function" == typeof e.onclick && e.onclick;
          e.onclick = function (e) {
            t && t(), o(e)
          }
        }

        function o(e) {
          var a = t.createElement("div");
          a.className = "heart", s.push({
            el: a,
            x: e.clientX - 5,
            y: e.clientY - 5,
            scale: 1,
            alpha: 1,
            color: c()
          }), t.body.appendChild(a)
        }

        function i(e) {
          var a = t.createElement("style");
          a.type = "text/css";
          try {
            a.appendChild(t.createTextNode(e))
          } catch (t) {
            a.styleSheet.cssText = e
          }
          t.getElementsByTagName("head")[0].appendChild(a)
        }

        function c() {
          return "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + ")"
        }

        var s = [];
        e.requestAnimationFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame || function (e) {
          setTimeout(e, 1e3 / 60)
        }, i(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"), n(), r()
      }(window, document);
    </script>
  













</body>
</html>
